////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Microsoft Corporation.  All rights reserved.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2012 Kentaro Sekimoto  All rights reserved.
////////////////////////////////////////////////////////////////////////////

#include <tinyhal.h>

//--//

#define FLASH_MANUFACTURER_CODE              0x0000  // not used
#define FLASH_DEVICE_CODE                    0x0000  // not used
#define FLASH_MEMORY_BASE                    FLASH_MEMORY_Base	// Don't forget to set!
#define FLASH_BLOCK_COUNT                    256
#define FLASH_BYTES_PER_BLOCK                2048
#define FLASH_BYTES_PER_SECTOR               2
#define FLASH_BLOCK_ERASE_TYPICAL_TIME_USEC  1000000 // not used
#define FLASH_SECTOR_WRITE_TYPICAL_TIME_USEC 10      // not used
#define FLASH_BLOCK_ERASE_MAX_TIME_USEC      4000000 // not used
#define FLASH_SECTOR_WRITE_MAX_TIME_USEC     100     // not used
#define FLASH_BLOCK_ERASE_ACTUAL_TIME_USEC   10000   // not used

//--//

// EBIU Information

#define FM3__CHIP_SELECT       0
#define FM3__WAIT_STATES       5 // not used
#define FM3__RELEASE_COUNTS    0
#define FM3__BIT_WIDTH         16
#define FM3__BASE_ADDRESS      FLASH_MEMORY_BASE
#define FM3__SIZE_IN_BYTES     FLASH_BLOCK_COUNT * FLASH_BYTES_PER_BLOCK
#define FM3__WP_GPIO_PIN       GPIO_PIN_NONE
#define FM3__WP_ACTIVE         FALSE

//--//

// BlockDeviceInformation

#define FM3__IS_REMOVABLE      FALSE
#define FM3__SUPPORTS_XIP      TRUE
#define FM3__WRITE_PROTECTED   FALSE
#define FM3__SUPP_COPY_BACK    FALSE
#define FM3__NUM_REGIONS       3

//#define BYTES_PER_SECTOR      16384
#define REGION1_XIP_ADDRESS     FLASH_MEMORY_BASE
#define REGION1_BYTES_PER_BLK   0x4000
#define REGION1_NUM_OF_BLOCKS   2

#define REGION2_XIP_ADDRESS     REGION1_XIP_ADDRESS + (REGION1_BYTES_PER_BLK * REGION1_NUM_OF_BLOCKS)
#define REGION2_BYTES_PER_BLK   0x18000
#define REGION2_NUM_OF_BLOCKS   1

#define REGION3_XIP_ADDRESS     REGION2_XIP_ADDRESS + (REGION2_BYTES_PER_BLK * REGION2_NUM_OF_BLOCKS)
#define REGION3_BYTES_PER_BLK   0x20000
#define REGION3_NUM_OF_BLOCKS   7

//--//

const BlockRange g_FM3_BlockRange1[] =
{
	{ BlockRange::BLOCKTYPE_BOOTSTRAP ,   0,   1 }  // 00000000 bootloader	32k
};

const BlockRange g_FM3_BlockRange2[] =
{
	{ BlockRange::BLOCKTYPE_CODE ,        0,   0 }  // 00008000 CLR     	96k
};

const BlockRange g_FM3_BlockRange3[] =
{
	{ BlockRange::BLOCKTYPE_CODE      ,   0,   3 }, // 00020000 CLR			512k
	{ BlockRange::BLOCKTYPE_DEPLOYMENT,   4,   5 }, // 000A0000 deployment	256k
	{ BlockRange::BLOCKTYPE_CONFIG    ,   6,   6 }  // 000E0000 Config		128k
};

const BlockRegionInfo  g_FM3_BlkRegion[FM3__NUM_REGIONS] =
{
    {
        REGION1_XIP_ADDRESS,        // ByteAddress   Start;           // Starting Sector address
        REGION1_NUM_OF_BLOCKS,      // UINT32        NumBlocks;       // total number of blocks in this region
        REGION1_BYTES_PER_BLK,      // UINT32        BytesPerBlock;   // Total number of bytes per block
        ARRAYSIZE_CONST_EXPR(g_FM3_BlockRange1),
        g_FM3_BlockRange1,
    },
    {
    	REGION2_XIP_ADDRESS,        // ByteAddress   Start;           // Starting Sector address
    	REGION2_NUM_OF_BLOCKS,      // UINT32        NumBlocks;       // total number of blocks in this region
    	REGION2_BYTES_PER_BLK,      // UINT32        BytesPerBlock;   // Total number of bytes per block
        ARRAYSIZE_CONST_EXPR(g_FM3_BlockRange2),
        g_FM3_BlockRange2,
    },
    {
    	REGION3_XIP_ADDRESS,        // ByteAddress   Start;           // Starting Sector address
    	REGION3_NUM_OF_BLOCKS,      // UINT32        NumBlocks;       // total number of blocks in this region
    	REGION3_BYTES_PER_BLK,      // UINT32        BytesPerBlock;   // Total number of bytes per block
        ARRAYSIZE_CONST_EXPR(g_FM3_BlockRange3),
        g_FM3_BlockRange3,
    }
};

//--//

#undef MEMORY_BLOCKTYPE_GCC_SPECIAL_CODE 

//--//

const BlockDeviceInfo g_FM3_DeviceInfo=
{
    {  
        FM3__IS_REMOVABLE,                  // BOOL Removable;
        FM3__SUPPORTS_XIP,                  // BOOL SupportsXIP;
        FM3__WRITE_PROTECTED,               // BOOL WriteProtected;
        FM3__SUPP_COPY_BACK                 // BOOL SupportsCopyBack
    },
    FLASH_SECTOR_WRITE_TYPICAL_TIME_USEC,   // UINT32 MaxSectorWrite_uSec;
    FLASH_BLOCK_ERASE_ACTUAL_TIME_USEC,     // UINT32 MaxBlockErase_uSec;
    FLASH_BYTES_PER_SECTOR,                 // UINT32 BytesPerSector;

    FLASH_MEMORY_Size,                      // UINT32 Size;

    FM3__NUM_REGIONS,                       // UINT32 NumRegions;
    g_FM3_BlkRegion,                        // const BlockRegionInfo* pRegions;
};

struct MEMORY_MAPPED_NOR_BLOCK_CONFIG g_FM3_BS_Config =
{
    { // BLOCK_CONFIG
        {
            FM3__WP_GPIO_PIN,               // GPIO_PIN             Pin;
            FM3__WP_ACTIVE,                 // BOOL                 ActiveState;
        },

        &g_FM3_DeviceInfo,                  // BlockDeviceinfo
    },

    { // CPU_MEMORY_CONFIG
        FM3__CHIP_SELECT,                   // UINT8  CPU_MEMORY_CONFIG::ChipSelect;
        TRUE,                               // UINT8  CPU_MEMORY_CONFIG::ReadOnly;
        FM3__WAIT_STATES,                   // UINT32 CPU_MEMORY_CONFIG::WaitStates;
        FM3__RELEASE_COUNTS,                // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts;
        FM3__BIT_WIDTH,                     // UINT32 CPU_MEMORY_CONFIG::BitWidth;
        FM3__BASE_ADDRESS,                  // UINT32 CPU_MEMORY_CONFIG::BaseAddress;
        FM3__SIZE_IN_BYTES,                 // UINT32 CPU_MEMORY_CONFIG::SizeInBytes;
        0,                                  // UINT8  CPU_MEMORY_CONFIG::XREADYEnable
        0,                                  // UINT8  CPU_MEMORY_CONFIG::ByteSignalsForRead
        0,                                  // UINT8  CPU_MEMORY_CONFIG::ExternalBufferEnable
    },

    0,                                      // UINT32 ChipProtection;
    FLASH_MANUFACTURER_CODE,                // UINT32 ManufacturerCode;
    FLASH_DEVICE_CODE,                      // UINT32 DeviceCode;
};

//--//

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rodata = "g_FM3_BS"
#endif

struct BlockStorageDevice g_FM3_BS;

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rodata 
#endif 

//--//

